Third Party Audio Library Linker Issues

Viewed 187

This is a total shot in the dark and it's probably a waste of time asking, but you never know. I am using GNAT Studio Community 2021 (Ada2012) and trying to get an audio library to work. I am well aware there are zero audio libraries written exclusively in Ada, so of course it's a mix of C, C++ with some Ada sample code.

What I have done so far:

Included all the directories I needed. Ticked the "Language" box under "Project Properties" to include the usage of C and C++ files to make them visible. C/P the required DLL's (included in the Audio library folder) into the "src" directory of my project.

So far, with everything above done it DOES compile, so I am half way to getting it to work. However, I get a slew of Linker errors, which seem to be referring to functions (they are C/C++ ones, not Ada) that are missing. This is despite me including all the relevant files and making them visible.

Here is what the compiler comes out with (I've cropped it from the first line as the rest is just a continuation with missing function defs from the same object file).

*

Compile
[Ada]          main.adb
Bind
[gprbind]      main.bexch
[Ada]          main.ali
Link
[link]         main.adb
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe:
libamos.a(oal.o):oal.cpp:(.text+0x10): undefined reference to
`__imp_alcOpenDevice'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe:
libamos.a(oal.o):oal.cpp:(.text+0x4c): undefined reference to
`__imp_alcCreateContext’

Here is the code I wrote to test if everything works.

with al_h;
with alc_h;
with snd;
with snd4ada;
with sndloop;


procedure Main is
begin
    null;
end Main;

For reference, here is the working code that comes with the library.

with text_io; use text_io;
with snd4ada;
with interfaces.c;
with interfaces.c.strings;
with ada.command_line;

procedure one is

    -- plays WAV file given on command line

    subtype glint is interfaces.c.int;

    linestr: string(1..80);
    last: natural;
    music: glint;

begin

if ada.command_line.argument_count = 1 then

    declare
        title : string := Ada.Command_Line.Argument(1);
    begin --declare


        snd4ada.initSnds;

        music:=snd4ada.initLoop( 
            interfaces.c.Strings.New_string(title));


        put_line("Hit <enter> to begin");
        get_line(linestr,last);

        snd4ada.playLoop(music);

        put_line("hit <enter> to end");
        get_line(linestr,last);

        snd4ada.stopLoop(music);

        snd4ada.termSnds;

    end; --declare

end if;
end one;

My guess is the problem is due to a Linker switch perhaps that I need to toggle under the project settings, so it can bind the C,C++ and Ada code together.

Am I just fighting a lost cause here? I would love to get this to work, and it seems my only problem is telling the linker where the declarations are (even though I have included all the relevant files into the project path).

If anyone can help, I would be hugely happy. If I knew how I would write my own Audio Library for Ada, but it seems third party is the only way to go. BTW - I did try to get BASS to work but that's a no go. This one is the closest to working - and it's annoying as the sample code produces an .exe that does indeed work. So it must be something I am doing wrong with the Linker.

EDIT

Here is the contents of my GPR file.

project Amos is

   for Source_Dirs use ("src", "External Libs/adaOal19oct21/adaOpenAL", "External Libs/adaOal19oct21/adaOpenAL/OalBinding", "External Libs/adaOal19oct21/adaOpenAL/OalBinding/incoal");
   for Object_Dir use "obj";
   for Main use ("main.adb");
   for Languages use ("Ada", "C", "C++");

end Amos;

Hey everyone. Yes, I am still tying to get Ada Open AL to work on GNAT 2021 Community Edition. I have been toggling a few things with no luck. A friend of mine is an Ada developer and he said he can get it to work on an older IDE which uses Windows NT?

I've made constant changes to my GPR file. Again, everything gets past the compiler but fails at the linker since it cannot find the object files, even though I have added all the switches. Here is my current GPR file.

project Knightmare is

   for Source_Dirs use ("src", "../Libs/adaOpenAL", "../Libs/adaOpenAL/OalBinding", "../Libs/adaOpenAL/OalBinding/incoal");
   for Object_Dir use "obj";
   for Main use ("main.adb");
   for Languages use ("Ada", "C", "C++");

   package Linker is
      for Switches ("c++") use ("g++", "-c", "-fdump-ada-spec", "-C", "oal.hpp", "-Iincoal");
   end Linker;

   package Compiler is
        for Switches ("c++") use ("g++", "-c", "../OalBinding/oal.cpp", "/-std=c++11", "/-fpermissive",
                                  "/-I..", "/-I../OalBinding", "/-I../OalBinding/incoal");
   end Compiler;

end Knightmare;

Language checked under "Project Properties" is Ada, C and C++. All required folders are included (as shown in the GPR). Could it be a "Dependency" I am missing? I have looked at the SH (shell scripts) as mentioned by the kind user below and in the comments but I cannot add Shell Script to the project because it says I have no compiler to handle it. I did find this file today however which could be the problem.

rm *.o
rm obj/*


g++ -c ../OalBinding/oal.cpp \
-std=c++11 \
-fpermissive \
-I.. \
-I../OalBinding \
-I../OalBinding/incoal



gnatmake $1 \
-D obj \
-I.. -I../OalBinding \
-largs \
-lc++ \
oal.o \
\
-framework CoreAudio \
-framework AudioUnit \
-framework AudioToolBox \
-framework OpenAL \
-pthread 

Is this what the linker is looking for to bind everything? If so, how do I tell the Ada/C/C++ linker to do that? Oh and for some reason the switch "-pthread" is not valid either which seems odd.

Here is a snipped output from the linker error.

\Source\knightmare.gpr
Bind
   [gprbind]      main.bexch
   [Ada]          main.ali
Link
   [link]         main.adb
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x10): undefined reference to `__imp_alcOpenDevice'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x4c): undefined reference to `__imp_alcCreateContext'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x6c): undefined reference to `__imp_alcMakeContextCurrent'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x88): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x9d): undefined reference to `__imp_alGenBuffers'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0xa6): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x113): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x13c): undefined reference to `__imp_alBufferData'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x145): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x1a8): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x1bd): undefined reference to `__imp_alGenSources'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x1c6): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x22b): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x245): undefined reference to `__imp_alSourcei'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x24e): undefined reference to `__imp_alGetError'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x2be): undefined reference to `__imp_alDeleteSources'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x2d3): undefined reference to `__imp_alDeleteBuffers'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x2f7): undefined reference to `__imp_alcDestroyContext'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x307): undefined reference to `__imp_alcCloseDevice'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x325): undefined reference to `__imp_alSourceStop'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x343): undefined reference to `__imp_alSourcePlay'
c:/gnat/2021/bin/../libexec/gcc/x86_64-w64-mingw32/10.3.1/ld.exe: libknightmare.a(oal.o):oal.cpp:(.text+0x36d): undefined reference to `__imp_alGetSourcei'
collect2.exe: error: ld returned 1 exit status
gprbuild: link of main.adb failed
gprbuild: failed command was: c:\gnat\2021\bin\g++.exe main.o b__main.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\al_h.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\alc_h.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\enemy.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\oal_hpp.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\player.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\knightmare.o C:\Users\Amynu\OneDrive\Documents\Knig
htmare\Source\obj\snd.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\sndloop.o C:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\snd4ada.o libknightmare.a -LC:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\ -LC:\Users\Amynu\OneDrive\Documents\Knightmare\Source\obj\ -LC:/gnat/2021/lib/gcc/x86_64-w64-mingw32/10.3.1/adalib/ C:/gnat/2021/lib/gcc/x86_64-w64-mingw32/10.3.1/adalib/libgnarl.a C:/gnat/2021/lib/gcc/x86_64-w64-mingw32/10.3.1/adalib/libgnat.a -Xlinker --stack=0x200000
,0x1000 -mthreads -shared-libgcc -o main.exe
[2021-11-24 10:53:20] process exited with status 4, 100% (11/11), elapsed time: 01.42s
Could not execute "debug set line breakpoint"

I know I am close to getting it to work. I even emailed the creators of Ada Open Al but nobody has gotten back to me now for three days. There are zero youtube videos on how to get it to work under GNAT 2021 Community, and what little information there is on the web is very sparse and unhelpful.

If anyone can point me to a possible solution I would be forever happy for it. BTW, I know there is an SDL binding for Ada but that only works on Win32 machines (it's pretty old), so that was out the window too.

1 Answers

lcmp.sh contains

rm *.o
rm obj/*


# first, create oal.o:
g++ ../OalBinding/oal.cpp -c \
-D obj \
-I.. \
-I../OalBinding \
-I../OalBinding/incoal


gnatmake $1 -o $1_gnu \
-D obj \
-O3 -gnat12 -I.. -I../OalBinding \
-largs \
oal.o \
-lstdc++ \
-lopenal -lpthread

so I’d expect your GPR to contain this (tested on macOS with the commented-out contents of package Linker, see ocmp.sh) using gprbuild -P sample:

project Sample is

   for Languages use ("ada", "c++");
   for Object_Dir use "obj";
   for Create_Missing_Dirs use "true";
   for Source_Dirs use (".", "..", "../OalBinding");

   for Main use ("one.adb", "two.adb");
   for Exec_Dir use ".";  -- unless you want the executables in Object_Dir!

   package Compiler is
      for Default_Switches ("ada") use ("-O3", "-gnat12");

      --  You'd have thought that these switches should be "-I..",
      --  "-I../OalBinding" etc; sadly, the compilation is run from
      --  the Object_Dir, ./obj, so the include directories are one
      --  more level up.
      --
      --  Someone put me right if there's a better way to do this!
      for Default_Switches ("c++") use
        ("-I../..", "-I../../OalBinding", "-I../../OalBinding/incoal");
   end Compiler;

   package Linker is
      for Default_Switches ("ada") use
        ("-lstdc++", "-lopenal", "-lpthread");

      -- These are the linker switches for macOS, see ocmp.sh.
      -- for Default_Switches ("ada") use
      --   ("-lstdc++",
      --    "-framework", "CoreAudio",
      --    "-framework", "AudioUnit",
      --    "-framework", "AudioToolBox",
      --    "-framework", "OpenAL");
   end Linker;

end Sample;

This works if your test program is in the adaExample/ directory; it gets a bit more complicated if you want to use the code here as a library, which would mean creating a library project.

Related