Cross compiling cppzmq for arm cannot find sodium.h - c++

I have a C++ application and I need to cross compile it for armv7. It needs 3 libraries:
cppzmq
Eigen
nlohmann/json
What I have
A raspberry compute module 3+ with Debian 9 Buster
Manjaro Linux (or windows I guess)
$ uname -a
Linux user 5.15.71-1-MANJARO #1 SMP PREEMPT Wed Sep 28 11:24:27 UTC 2022 x86_64 GNU/Linux
A project set up with CLion and Meson by me following the basic cross compiling tutorial (see below for files content)
arm-none-linux-gnueabihf toolchain
meson txt file for setting up the toolchain
meson.build file
meson .wrap files for easier dependencies management
What is my issue
This is my first time doing cross compiling or working with C in general, I know I'm really near the solution but I'm wasting a little too much time on this.
I'm able to compile Eigen and Json
I added catch2 and libzmq to solve some issues and I can compile these too
libobsd and libsodium are compiled but not picked up by cppzmq
I think I need to pass the compiled libobsd and libsodium as libraries to cppzmq but I'm not sure. Error log cleaned up:
Executing subproject cppzmq
cppzmq| Project name: cppzmq
cppzmq| Project version: 4.8.1
cppzmq| C++ compiler for the host machine: /usr/bin/arm-none-linux-gnueabihf-g++ (gcc 10.3.1 "arm-none-linux-gnueabihf-g++ (GNU Toolchain for the A-profile Architecture 10.3-2021.07 (arm-10.29)) 10.3.1 20210621")
cppzmq| C++ linker for the host machine: /usr/bin/arm-none-linux-gnueabihf-g++ ld.bfd 10.3-2021
cppzmq| C++ compiler for the build machine: c++ (gcc 12.2.0 "c++ (GCC) 12.2.0")
cppzmq| C++ linker for the build machine: c++ ld.bfd 2.39.0
cppzmq| Dependency libzmq from subproject subprojects/zeromq-4.3.4 found: YES undefined
cppzmq| Dependency threads found: YES unknown (cached)
cppzmq| Dependency catch2 from subproject subprojects/Catch2-3.1.0 found: YES 3.1.0
cppzmq| Build targets in project: 149
cppzmq| Subproject cppzmq finished.
meson 0.0.1
Subprojects
catch2 : YES
cppzmq : YES
eigen : YES
json : YES
libobsd : YES
libzmq : YES 2 warnings
User defined options
Cross files: /my_path/meson/raspberry-cm3+.txt
backend : ninja
Found ninja-1.11.1 at /usr/bin/ninja
Cleaning... 107 files.
[1/270] Compiling C++ object subprojects/zeromq-4.3.4/libobjects.a.p/src_msg.cpp.o
FAILED: subprojects/zeromq-4.3.4/libobjects.a.p/src_msg.cpp.o
/usr/bin/arm-none-linux-gnueabihf-g++ -Isubprojects/zeromq-4.3.4/libobjects.a.p -Isubprojects/zeromq-4.3.4 -I../srcdir/subprojects/zeromq-4.3.4 -I../srcdir/subprojects/zeromq-4.3.4/include -Isubprojects/zeromq-4.3.4/__CMake_build -I../srcdir/subprojects/zeromq-4.3.4/__CMake_build -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=gnu++11 -O0 -g -fPIC -Wno-tautological-constant-compare -O3 -DNDEBUG -DZMQ_CUSTOM_PLATFORM_HPP -D_GNU_SOURCE -D_REENTRANT -D_THREAD_SAFE -MD -MQ subprojects/zeromq-4.3.4/libobjects.a.p/src_msg.cpp.o -MF subprojects/zeromq-4.3.4/libobjects.a.p/src_msg.cpp.o.d -o subprojects/zeromq-4.3.4/libobjects.a.p/src_msg.cpp.o -c ../srcdir/subprojects/zeromq-4.3.4/src/msg.cpp
In file included from ../srcdir/subprojects/zeromq-4.3.4/src/msg.cpp:31:
../srcdir/subprojects/zeromq-4.3.4/src/compat.hpp:42:10: fatal error: bsd/string.h: No such file or directory
42 | #include <bsd/string.h>
| ^~~~~~~~~~~~~~
compilation terminated.
[2/270] Compiling C++ object subprojects/zeromq-4.3.4/libobjects.a.p/src_ipc_address.cpp.o
FAILED: subprojects/zeromq-4.3.4/libobjects.a.p/src_ipc_address.cpp.o
/usr/bin/arm-none-linux-gnueabihf-g++ -Isubprojects/zeromq-4.3.4/libobjects.a.p -Isubprojects/zeromq-4.3.4 -I../srcdir/subprojects/zeromq-4.3.4 -I../srcdir/subprojects/zeromq-4.3.4/include -Isubprojects/zeromq-4.3.4/__CMake_build -I../srcdir/subprojects/zeromq-4.3.4/__CMake_build -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=gnu++11 -O0 -g -fPIC -Wno-tautological-constant-compare -O3 -DNDEBUG -DZMQ_CUSTOM_PLATFORM_HPP -D_GNU_SOURCE -D_REENTRANT -D_THREAD_SAFE -MD -MQ subprojects/zeromq-4.3.4/libobjects.a.p/src_ipc_address.cpp.o -MF subprojects/zeromq-4.3.4/libobjects.a.p/src_ipc_address.cpp.o.d -o subprojects/zeromq-4.3.4/libobjects.a.p/src_ipc_address.cpp.o -c ../srcdir/subprojects/zeromq-4.3.4/src/ipc_address.cpp
In file included from ../srcdir/subprojects/zeromq-4.3.4/src/ipc_address.cpp:31:
../srcdir/subprojects/zeromq-4.3.4/src/compat.hpp:42:10: fatal error: bsd/string.h: No such file or directory
42 | #include <bsd/string.h>
| ^~~~~~~~~~~~~~
compilation terminated.
[3/270] Compiling C++ object subprojects/zeromq-4.3.4/libobjects.a.p/src_curve_mechanism_base.cpp.o
FAILED: subprojects/zeromq-4.3.4/libobjects.a.p/src_curve_mechanism_base.cpp.o
/usr/bin/arm-none-linux-gnueabihf-g++ -Isubprojects/zeromq-4.3.4/libobjects.a.p -Isubprojects/zeromq-4.3.4 -I../srcdir/subprojects/zeromq-4.3.4 -I../srcdir/subprojects/zeromq-4.3.4/include -Isubprojects/zeromq-4.3.4/__CMake_build -I../srcdir/subprojects/zeromq-4.3.4/__CMake_build -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=gnu++11 -O0 -g -fPIC -Wno-tautological-constant-compare -O3 -DNDEBUG -DZMQ_CUSTOM_PLATFORM_HPP -D_GNU_SOURCE -D_REENTRANT -D_THREAD_SAFE -MD -MQ subprojects/zeromq-4.3.4/libobjects.a.p/src_curve_mechanism_base.cpp.o -MF subprojects/zeromq-4.3.4/libobjects.a.p/src_curve_mechanism_base.cpp.o.d -o subprojects/zeromq-4.3.4/libobjects.a.p/src_curve_mechanism_base.cpp.o -c ../srcdir/subprojects/zeromq-4.3.4/src/curve_mechanism_base.cpp
In file included from ../srcdir/subprojects/zeromq-4.3.4/src/curve_mechanism_base.cpp:32:
../srcdir/subprojects/zeromq-4.3.4/src/curve_mechanism_base.hpp:38:10: fatal error: sodium.h: No such file or directory
38 | #include "sodium.h"
| ^~~~~~~~~~
compilation terminated.
Files Details
raspberry-cm3+.txt to set up the cross compiling
[binaries]
c = '/usr/bin/arm-none-linux-gnueabihf-gcc'
cpp = '/usr/bin/arm-none-linux-gnueabihf-g++'
ar = '/usr/bin/arm-none-linux-gnueabihf-ar'
strip = '/usr/bin/arm-none-linux-gnueabihf-strip'
[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7hl'
endian = 'little'
meson.build to set up the project
project('meson', 'cpp', version : '0.0.1')
cpp = meson.get_compiler('cpp')
os = target_machine.system()
cmake = import('cmake')
dep_eigen = subproject('eigen').get_variable('eigen_dep')
lib_zmq = cmake.subproject('libzmq')
dep_zmq = lib_zmq.dependency ('libzmq')
# lib_libsodium = cmake.subproject('libsodium')
# dep_libsodium = lib_libsodium.dependency ('sodium')
# lib_libsodium = cpp.find_library('libsodium', required: false)
# if lib_libsodium.found()
# dep_sqlitecpp = lib_libsodium
# endif
dep_catch = subproject('catch2').get_variable('catch2_dep')
dep_libobsd = subproject('libobsd').get_variable('libobsd_dep')
if cpp.has_header('zmq.hpp')
# cppzmq is a header-only dependency, so if we already have the
# header in place, we don't need to actually change anything
dep_cppzmq = [] #declare_dependency()
else
dep_cppzmq = subproject('cppzmq').get_variable('cppzmq_dep')
endif
if cpp.has_header('nlohmann/json.hpp')
dep_json = [] #declare_dependency()
else
dep_json = subproject('json').get_variable('nlohmann_json_dep')
endif
deps = [
dep_eigen,
# dep_libsodium,
dep_libobsd,
dep_catch,
dep_zmq,
dep_cppzmq,
dep_json
]
executable(
'demo',
'main.cpp',
dependencies :deps
)
Wrap Files
catch2, cppzmq, eigen, libobsd and json are the default ones from the meson wrap repository
libsodium.wrap (custom repo to use cmake)
[wrap-git]
directory = libsodium-1.0.18
url = https://github.com/robinlinden/libsodium-cmake.git
revision = master
depth = 1
clone-recursive = true
[provide]
libsodium = libsodium_dep
sodium = sodium_dep
libzmq.wrap
[wrap-file]
directory = zeromq-4.3.4
source_url = https://github.com/zeromq/libzmq/releases/download/v4.3.4/zeromq-4.3.4.tar.gz
source_filename = zeromq-4.3.4.tar.gz
source_hash = c593001a89f5a85dd2ddf564805deb860e02471171b3f204944857336295c3e5
[provide]
libzmq = libzmq_dep
Notes
I don't mind switching build tools to CMake for example
there is another toolchain on the AUR repository I don't know if it could change anything (trying right now)
???
profit

Related

Controlling scons environment checking options

I'm trying to build mongodb (open source version 4.2) which uses python and scons for building. The problem relates to scons rather than mongodb.
My build fails very early with Couldn't find OpenSSL crypto.h header and library. Verbose details are:
file /.../SConstruct,line 3042:
Configure(confdir = build/scons/opt/sconf_temp)
scons: Configure: Checking for SSLeay_version(0) in C library crypto...
build/scons/opt/sconf_temp/conftest_d6743137aeb7fb2674cc9632f9989034_0.c <-
|
|
|#include "openssl/crypto.h"
|
|int
|main() {
| SSLeay_version(0);
|return 0;
|}
|
gcc -o build/scons/opt/sconf_temp/conftest_d6743137aeb7fb2674cc9632f9989034_0.o -c -std=c11 -ffp-contract=off -fno-omit-frame-pointer -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -Werror -O2 -Wno-unused-local-typedefs -Wno-unused-function -Wno-deprecated-declarations -Wno-unused-const-variable -Wno-unused-but-set-variable -Wno-missing-braces -Wno-exceptions -fstack-protector-strong -fno-builtin-memcmp -fPIE -DNDEBUG -D_XOPEN_SOURCE=700 -D_GNU_SOURCE build/scons/opt/sconf_temp/conftest_d6743137aeb7fb2674cc9632f9989034_0.c
cc1: error: command-line option '-Wno-exceptions' is valid for C++/ObjC++ but not for C [-Werror]
cc1: all warnings being treated as errors
scons: Configure: no
I'm using Arch Linux which has multiple OpenSSL packages, and the default 3.0 is not compatible with mongodb source. I also have OpenSSL 1.1 and 1.0 installed, and can switch with e.g. gcc -I/usr/include/openssl-1.1.
Unfortunately I have not found a way to instruct SConstruct to use this flag in the command lines it generates to check the environment. I have tried CFLAGS, CCFLAGS, CPPPATH both as environment variables and scons command line parameters.
I also tried reverse enginering it, and tracked this to Conftest and TryBuild but it's not obvious how I can influance theses from the command line, so I'm trying my luck with you guys before going deeper in scons code.
If you look at the SConstruct and search for openssl, you'll find this blurb under the logic to detect on macOS
NOTE: Recent versions of macOS no longer ship headers for the system OpenSSL libraries.
NOTE: Either build without the --ssl flag, or describe how to find OpenSSL.
NOTE: Set the include path for the OpenSSL headers with the CPPPATH SCons variable.
NOTE: Set the library path for OpenSSL libraries with the LIBPATH SCons variable.
NOTE: If you are using HomeBrew, and have installed OpenSSL, this might look like:
\tscons CPPPATH=/usr/local/opt/openssl/include LIBPATH=/usr/local/opt/openssl/lib ...
NOTE: Consult the output of 'brew info openssl' for details on the correct paths."""
I'd bet if you did the same but pointed at the proper locations on your system for the openssl libs and header files, you'd be able to build.
(see: https://github.com/mongodb/mongo/blob/r4.2.0/SConstruct#L3015 )

How to build openFrameworks as a shard library on macOS

I'm trying to build OF as a shared library (.so) in macOS.
I added the following to my app's config.make file.
APPNAME = myApp.so
PROJECT_LDFLAGS = -rdynamic -shared -undefined dynamic_lookup
PROJECT_OPTIMIZATION_CFLAGS_RELEASE = -O3
But when I build the project using make, it actually generates an Application file myApp.so.app which is not a shared library.
How can I properly build OF as a shared library in macOS?
I could successfully build OF as a shared library with the following:
APPNAME = myApp.so
PROJECT_CFLAGS = -Wall
PROJECT_LDFLAGS = -dynamiclib -Wl,-undefined -Wl,dynamic_lookup
PROJECT_OPTIMIZATION_CFLAGS_RELEASE = -O3

Building audio analysis library Essentia failed with Gaia support

I am trying to build Essentia (https://github.com/MTG/essentia), an audio analysis library, with Gaia (https://github.com/MTG/gaia) support in Debian 9.0 from source. Before that, one of its dependencies, namely Gaia, was successfully built, also, from source. It was installed in /usr/local/.
When it comes to Essentia, compilation of sources fails with the following errors:
[...]
In file included from ../src/algorithms/essentia_algorithms_reg.cpp:21:0:
../src/algorithms/highlevel/gaiatransform.h: At global scope:
../src/algorithms/highlevel/gaiatransform.h:37:10: error: ‘TransfoChain’ in namespace ‘gaia2’ does not name a type
gaia2::TransfoChain _history;
^~~~~~~~~~~~
../src/algorithms/highlevel/gaiatransform.h: In constructor ‘essentia::standard::GaiaTransform::GaiaTransform()’:
../src/algorithms/highlevel/gaiatransform.h:47:5: error: ‘init’ is not a member of ‘gaia2’
gaia2::init();
^~~~~
../src/algorithms/highlevel/gaiatransform.h:47:5: note: suggested alternative:
In file included from ../src/essentia/algorithmfactory.h:27:0,
from ../src/algorithms/essentia_algorithms_reg.cpp:1:
../src/essentia/essentia.h:46:6: note: ‘essentia::init’
void init();
^~~~
The file where the error lies is /src/algorithms/essentia_algorithms_reg.cpp and here is the command which the file is compiled with:
/usr/bin/g++ -pipe -Wall -std=c++03 -msse -msse2 -mfpmath=sse -O2 -fPIC -pthread -Isrc -I../src -Isrc/essentia -I../src/essentia -Isrc/essentia/scheduler -I../src/essentia/scheduler -Isrc/essentia/streaming -I../src/essentia/streaming -Isrc/essentia/streaming/algorithms -I../src/essentia/streaming/algorithms -Isrc/essentia/utils -I../src/essentia/utils -Isrc/3rdparty -I../src/3rdparty -Isrc/3rdparty/spline -I../src/3rdparty/spline -Isrc/3rdparty/vamp-plugin-sdk-2.4 -I../src/3rdparty/vamp-plugin-sdk-2.4 -I/usr/include/x86_64-linux-gnu -I/usr/include/taglib -I/usr/local/include -I/usr/include/qt4 -I/usr/include/qt4/QtCore -I/usr/local/include/gaia2/ -DHAVE_AVCODEC=1 -DHAVE_AVFORMAT=1 -DHAVE_AVUTIL=1 -DHAVE_AVRESAMPLE=1 -DHAVE_SAMPLERATE=1 -DHAVE_TAGLIB=1 -DHAVE_YAML=1 -DHAVE_FFTW=1 -DHAVE_GAIA2=1 -D__STDC_CONSTANT_MACROS -DPYTHONDIR="/usr/local/lib/python2.7/dist-packages" -DPYTHONARCHDIR="/usr/local/lib/python2.7/dist-packages" -DHAVE_PYEMBED=1 -DHAVE_PYEXT=1 -DHAVE_PYTHON_H=1 ../src/algorithms/essentia_algorithms_reg.cpp -c -o/home/hamidi/essentia/build/src/algorithms/essentia_algorithms_reg.cpp.1.o -fPIC -v
g++'s -v option gave me the actual paths visited by the linker (nothing bad in there, I think, but for the sake of completeness):
#include "..." search starts here:
#include <...> search starts here:
src
../src
src/essentia
../src/essentia
src/essentia/scheduler
../src/essentia/scheduler
src/essentia/streaming
../src/essentia/streaming
src/essentia/streaming/algorithms
../src/essentia/streaming/algorithms
src/essentia/utils
../src/essentia/utils
src/3rdparty
../src/3rdparty
src/3rdparty/spline
../src/3rdparty/spline
src/3rdparty/vamp-plugin-sdk-2.4
../src/3rdparty/vamp-plugin-sdk-2.4
/usr/include/taglib
/usr/include/qt4
/usr/include/qt4/QtCore
/usr/local/include/gaia2/
/usr/include/c++/6
/usr/include/x86_64-linux-gnu/c++/6
/usr/include/c++/6/backward
/usr/lib/gcc/x86_64-linux-gnu/6/include
/usr/local/include
/usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
Here are the files (github repo) involved in the error:
MTG/gaia/blob/master/src/gaia.h
MTG/gaia/blob/master/src/transformation.h#L106
/MTG/essentia/blob/master/src/algorithms/highlevel/gaiatransform.h
It is finally an error that occurred while configuring Gaia that caused the problem. Actually, rather than using merely the following options for configuration:
./waf configure --with-python-bindings --with-asserts --with-cyclops
the option --with-stlfacade was added by inadvertence. This option is not compatible when using Gaia in conjunction with Essentia.

Upgraded to unofficial wxWidgets 3.0 = > Fatal error wx/wx.h: No such file or directory

When I compile my project:
----------------------------------------------------------------------
wxFlasher configuration :
+ DEBUG = 0
+ UNICODE = 1
+ STATIC = 0
+ WX_VERSION = 3.0.2
+ SRC_DIR = /home/barnaud/dev/wxFlasher/wxFlasher/src
+ BUILD_DIR_BASE = /home/barnaud/dev/wxFlasher/wxFlasher/build_gcc/releaseu
+ OUT_DIR = /home/barnaud/dev/wxFlasher/wxFlasher/out_gcc/releaseu
+ GCC_PATH = /usr/bin/gcc
+ GCC_VERSION = gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
----------------------------------------------------------------------
Generating Main/Headers.h.gch...
/home/barnaud/dev/wxFlasher/wxFlasher/src/Main/Headers.h:18:23: fatal error: wx/wxprec.h: Aucun fichier ou dossier de ce type
#include <wx/wxprec.h>
I well installed the libraries:
$ wx-config --libs
-L/usr/lib/x86_64-linux-gnu -pthread -lwx_gtk2u_unofficial_xrc-3.0 -lwx_gtk2u_unofficial_webview-3.0 -lwx_gtk2u_unofficial_html-3.0 -lwx_gtk2u_unofficial_qa-3.0 -lwx_gtk2u_unofficial_adv-3.0 -lwx_gtk2u_unofficial_core-3.0 -lwx_baseu_unofficial_xml-3.0 -lwx_baseu_unofficial_net-3.0 -lwx_baseu_unofficial-3.0
cxxflags output :
wx-config --cxxflags
-I/usr/lib/x86_64-linux-gnu/wx/include/gtk2-unicode-3.0-unofficial -I/usr/include/wx-3.0-unofficial -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread
Now, how can I include the library in my project?
Look at the compiler command line (by running make -n if necessary, i.e. if your makefile hides it by default) and check if it uses the correct flags from wx-config. If it does, also check that you ran make install after building wxWidgets so that the headers are indeed available in the directory appearing in wx-config --cxxflags output.

Why the success of SCons build depends on variant_dir name?

I am bored to death with such behavior. So in SConstruct file we have the last string like this one:
import compilers, os
env = Environment(ENV = os.environ, TOOLS = ['default'])
def set_compiler(compiler_name):
env.Replace(FORTRAN = compiler_name)
env.Replace(F77 = compiler_name)
env.Replace(F90 = compiler_name)
env.Replace(F95 = compiler_name)
def set_flags(flags):
env.Replace(FORTRANFLAGS = flags)
env.Replace(F77FLAGS = flags)
env.Replace(F90FLAGS = flags)
env.Replace(F95FLAGS = flags)
mod_dir_prefix = {
"gfortran": "-J ",
"ifort": "-???",
"pgfortran": "-module "
}
flags = {
("gfortran", "debug"): "-O0 -g -Wall -Wextra -pedantic -fimplicit-none -fbounds-check -fbacktrace",
("gfortran", "release"): "-O3",
("pgfortran", "debug"): "-O0 -g -C -traceback",
("pgfortran", "release"): "-O4"
}
if not GetOption('clean'):
print "\nAvailable Fortran compilers:\n"
for k, v in compilers.compilers_dict().iteritems():
print "%10s : %s" % (k, v)
compiler = raw_input("\nChoose compiler: ")
set_compiler(compiler)
debug_or_release = raw_input("\nDebug or release: ")
set_flags(flags[(compiler, debug_or_release)])
env.Replace(FORTRANMODDIRPREFIX = mod_dir_prefix[compiler])
env.Replace(LINK = compiler)
env.Replace(LINKCOM = "$LINK -o $TARGET $LINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS")
env.Replace(LINKFLAGS = "")
env.Replace(FORTRANMODDIR = '#Mod')
Export('env')
SConscript('Sources/SConscript', variant_dir='Build', duplicate=0)
compilers.py is my own module to find some Fortran compilers which are available.
In Sources folder we have a couple of Fortran source files.
Sources\SConscript
Import('env')
env.Program('app', Glob('*.f90'))
Scons supports Fortran and everything works fine.
gfortran -o Temp\kinds.o -c -O3 -JMod Sources\kinds.f90
gfortran -o Temp\math.o -c -O3 -JMod Sources\math.f90
gfortran -o Temp\sorts.o -c -O3 -JMod Sources\sorts.f90
gfortran -o Temp\utils.o -c -O3 -JMod Sources\utils.f90
gfortran -o Temp\main.o -c -O3 -JMod Sources\main.f90
gfortran -o Temp\app.exe Temp\kinds.o Temp\main.o Temp\math.o Temp\sorts.o Temp\utils.o
scons: done building targets.
After renaming variant_dir name to let say #Bin or #Build we get error message:
gfortran -o Bin\kinds.o -c -O3 -JMod Sources\kinds.f90
gfortran -o Bin\main.o -c -O3 -JMod Sources\main.f90
Sources\main.f90:3.11:
USE sorts
1
Fatal Error: Can't open module file 'sorts.mod' for reading at (1): No such file or directory
Of course the order of compilation matters. But why it depends on variant_dir name? Seems like a bug, but maybe I'm doing something wrong.
P.S. This behavior doesn't depend on duplicate variable value.
P.P.S. Tested with SCons 2.0.1 on Windows with Python 2.7 and Mac OS X with Python 2.5.1.
This is a reply to an old thread, but I had virtually the same problem and needed to dig around for a solution.
Firstly, your build order is probably off because the dependency scanner for Fortran does not work properly. Try running
scons [your_arguments] -n --tree=all | less
which won't actually compile anything but show you the commands and in the end will print the dependency tree as Scons sees it.
A possible solution:
Try adding the line (I added your source for context):
env.Replace(FORTRANMODDIR = '#Mod')
env.Replace(FORTRANPATH = '.' ]
Export('env')
As far as I understand, paths are relative to the "virtual" location of the SConscript file (i.e. the src directory or the variant build directory), this should add the directory containing the source files to the scanner's search path.
In my version of scons (2.3.0), I cannot use the duplicate=0 argument, since it automatically inserts the original source directory into the module path, causing the command line to look like -module build/ -module src/ (ifort) and essentially overriding my preference not to clutter the source directory. This might be a bug, though.