Skip to content

Commit

Permalink
Use autoconf in the source-code FMUs
Browse files Browse the repository at this point in the history
By using autoconf, we move a lot of the work from the user of the
Makefiles to autoconf itself.

To try it out, cross-compiling for multiple platforms (with the FMU
unzipped to M.fmutmp):

(for arch in x86_64-w64-mingw32 x86_64-linux-gnu arm-linux-gnueabihf \
    i686-linux-gnu i686-w64-mingw32
do
  (cd M.fmutmp/sources/ && \
   ./configure --host=$arch CFLAGS=-Os && \
   make -j6) || exit 1;
done)

So it is enough to pass the host and optionally CFLAGS (on Ubuntu).
Recommended packages on an x86_64 host:
apt-get install gcc-arm-linux-gnueabihf libc6-dev:i386 gcc-mingw-w64

Note that installing gcc-multilib conflicts with gcc-arm, which means
you need the i386 libc6 headers.
  • Loading branch information
sjoelund authored and OpenModelica-Hudson committed Nov 9, 2015
1 parent d77c3cf commit e89eaf5
Show file tree
Hide file tree
Showing 15 changed files with 231 additions and 30 deletions.
18 changes: 16 additions & 2 deletions Compiler/Script/CevalScriptBackend.mo
Expand Up @@ -2638,7 +2638,7 @@ algorithm
GlobalScript.SymbolTable st;
list<String> libs;
Values.Value outValMsg;
String file_dir, FMUVersion, FMUType, fileNamePrefix, str, fmutmp, quote;
String file_dir, FMUVersion, FMUType, fileNamePrefix, str, fmutmp, quote, cmd;
Boolean isWindows = System.os() == "Windows_NT";
case (cache,env,_,st,FMUVersion,FMUType,fileNamePrefix,_,_) /* mo file directory */
equation
Expand All @@ -2657,15 +2657,29 @@ algorithm
unzip(...);
*/
// CevalScript.compileModel(fileNamePrefix , libs, workingDir=fmutmp+"/sources", makeVars={"CC=arm-linux-gnueabi-gcc","FMIPLATFORM=arm-linux-gnueabi","DLLEXT=.so"});
cmd = "cd \"" + fmutmp+"/sources\" && ./configure "+
" --host="+System.getTriple()+
" --build="+System.getTriple()+
" --with-dynamic-om-runtime"+
" CC="+quote+System.getCCompiler()+quote+
" CFLAGS="+quote+System.stringReplace(System.getCFlags(),"${MODELICAUSERCFLAGS}","")+quote+
" LDFLAGS="+quote+("-L'"+Settings.getInstallationDirectoryPath()+"/lib/"+System.getTriple()+"/omc' "+
"-Wl,-rpath,'"+Settings.getInstallationDirectoryPath()+"/lib/"+System.getTriple()+"/omc' "+
System.getLDFlags()+" "+(if staticSourceCodeFMU then "" else System.getRTLibsSim()))+quote+
(if staticSourceCodeFMU then " --with-dynamic-om-runtime" else "");
// print(cmd + "\n");
0=System.systemCall(cmd, outFile=fileNamePrefix+".log");
CevalScript.compileModel(fileNamePrefix , libs, workingDir=fmutmp+"/sources", makeVars={
/*
"CC="+System.getCCompiler(),
"CFLAGS="+quote+System.getCFlags()+quote,
"CPPFLAGS=",
"LDFLAGS="+quote+System.getLDFlags()+" "+(if staticSourceCodeFMU then "" else System.getRTLibsSim()) + quote,
"LDFLAGS="+quote+ + quote,
"FMIPLATFORM="+System.modelicaPlatform(),
"DLLEXT="+System.getDllExt(),
"LD="+quote+System.getLinker()+quote,
if staticSourceCodeFMU then "OPENMODELICA_DYNAMIC=" else "OPENMODELICA_DYNAMIC=1"
*/
});
// CevalScript.compileModel(fileNamePrefix , libs, workingDir=fmutmp+"/sources", makeVars={});
System.removeDirectory(fmutmp);
Expand Down
2 changes: 1 addition & 1 deletion Compiler/Template/CodegenC.tpl
Expand Up @@ -864,7 +864,6 @@ template simulationFile(SimCode simCode, String guid, Boolean isModelExchangeFMU
#if defined(__cplusplus)
extern "C" {
#endif
int measure_time_flag = <% if profileHtml() then "5" else if profileSome() then "1" else if profileAll() then "2" else "0" %>;
<%functionInput(modelInfo, modelNamePrefixStr)%>
Expand Down Expand Up @@ -997,6 +996,7 @@ template simulationFile(SimCode simCode, String guid, Boolean isModelExchangeFMU
{
int res;
DATA simulation_data;
measure_time_flag = <% if profileHtml() then "5" else if profileSome() then "1" else if profileAll() then "2" else "0" /* Would be good if this was not a global variable...*/ %>;
<%mainInit%>
<%mainTop(mainBody,"https://trac.openmodelica.org/OpenModelica/newticket")%>
Expand Down
36 changes: 13 additions & 23 deletions Compiler/Template/CodegenFMU.tpl
Expand Up @@ -80,7 +80,7 @@ case sc as SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
let()= textFile(fmumodel_identifierFile(simCode,guid,FMUVersion), '<%fileNamePrefixTmpDir%>_FMU.c')
let()= textFile(fmuModelDescriptionFile(simCode,guid,FMUVersion,FMUType), '<%fileNamePrefix%>.fmutmp/modelDescription.xml')
let()= textFile(fmudeffile(simCode,FMUVersion), '<%fileNamePrefix%>.fmutmp/sources/<%fileNamePrefix%>.def')
let()= textFile(fmuMakefile(target,simCode,FMUVersion), '<%fileNamePrefix%>.fmutmp/sources/Makefile')
let()= textFile(fmuMakefile(target,simCode,FMUVersion), '<%fileNamePrefix%>.fmutmp/sources/Makefile.in')
let()= textFile('# Dummy file so OMDEV Compile.bat works<%\n%>include Makefile<%\n%>', '<%fileNamePrefix%>.fmutmp/sources/<%fileNamePrefix%>.makefile')
let()= textFile(fmuSourceMakefile(simCode,FMUVersion), '<%fileNamePrefix%>_FMU.makefile')
"" // Return empty result since result written to files directly
Expand Down Expand Up @@ -1006,7 +1006,7 @@ match platform
<%\t%>$(LD) -o <%modelNamePrefix%>$(DLLEXT) $(MAINOBJ) $(OFILES) $(RUNTIMEFILES) <%dirExtra%> <%libsPos1%> <%libsPos2%> $(LDFLAGS)
<%\t%>mkdir -p ../binaries/$(FMIPLATFORM)
<%\t%>cp <%fileNamePrefix%>$(DLLEXT) <%fileNamePrefix%>_FMU.libs ../binaries/$(FMIPLATFORM)/
<%\t%>rm -f <%fileNamePrefix%>.def <%fileNamePrefix%>.o <%fileNamePrefix%>$(DLLEXT) $(MAINOBJ) $(OFILES) $(RUNTIMEFILES)
<%\t%>rm -f <%fileNamePrefix%>.def <%fileNamePrefix%>.o <%fileNamePrefix%>$(DLLEXT) $(MAINOBJ) $(OFILES) $(RUNTIMEFILES) Makefile config.status config.log
<%\t%>cd .. && rm -f ../<%fileNamePrefix%>.fmu && zip -r ../<%fileNamePrefix%>.fmu *

>>
Expand All @@ -1033,7 +1033,7 @@ let common =
OMC_MINIMAL_RUNTIME=1
OMC_FMI_RUNTIME=1
include $(RUNTIMEDIR)/Makefile.objs
ifeq ($(OPENMODELICA_DYNAMIC),)
ifneq ($(NEED_RUNTIME),)
RUNTIMEFILES=$(FMI_ME_OBJS:%=$(RUNTIMEDIR)/%.o)
endif
>>
Expand Down Expand Up @@ -1131,27 +1131,16 @@ case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__), simula
let platformstr = makefileParams.platform
<<
# Makefile generated by OpenModelica

CC=@CC@
CFLAGS=@CFLAGS@
LD=@CC@ -shared
LDFLAGS=@LDFLAGS@ @LIBS@
DLLEXT=@DLLEXT@
NEED_RUNTIME=@NEED_RUNTIME@
NEED_DGESV=@NEED_DGESV@
FMIPLATFORM=@FMIPLATFORM@
# Note: Simulation of the fmu with dymola does not work with -finline-small-functions (enabled by most optimization levels)
override CPPFLAGS += -Iinclude/ -Iinclude/fmi<%if isFMIVersion20(FMUVersion) then "2" else "1"%> -I. <%makefileParams.includes ; separator=" "%> <% if Flags.isSet(Flags.FMU_EXPERIMENTAL) then '-DFMU_EXPERIMENTAL'%>
ifeq ($(OPENMODELICA_DYNAMIC),)
override CPPFLAGS += -DOMC_MINIMAL_RUNTIME=1 -DCMINPACK_NO_DLL=1
override LDFLAGS += -L"<%makefileParams.omhome%>/lib/<%getTriple()%>/omc"
else
override LDFLAGS += -L"<%makefileParams.omhome%>/lib/<%getTriple()%>/omc" -Wl,-rpath,'<%makefileParams.omhome%>/lib/<%getTriple()%>/omc' <%makefileParams.ldflags%> <%makefileParams.runtimelibs%> <%dirExtra%>
endif

ifeq ($(DLLEXT),)
no-dll:
<%\t%>@echo "You need to set DLLEXT=.so or similar when calling this makefile"
<%\t%>@false
endif

ifeq ($(FMIPLATFORM),)
no-fmiplatform:
<%\t%>@echo "You need to set FMIPLATFORM=linux32 or similar when calling this makefile"
<%\t%>@false
endif
CPPFLAGS = @CPPFLAGS@ -Iinclude/ -Iinclude/fmi<%if isFMIVersion20(FMUVersion) then "2" else "1"%> -I. <%makefileParams.includes ; separator=" "%> <% if Flags.isSet(Flags.FMU_EXPERIMENTAL) then '-DFMU_EXPERIMENTAL'%>

<%common%>

Expand Down Expand Up @@ -1182,6 +1171,7 @@ template fmuSourceMakefile(SimCode simCode, String FMUVersion)
fmu:
<%\t%>rm -f <%fileNamePrefix%>.fmutmp/sources/<%fileNamePrefix%>_init.xml<%/*Already translated to .c*/%>
<%\t%>cp -a <%makefileParams.omhome%>/include/omc/c/* <%includedir%>
<%\t%>cp -a <%makefileParams.omhome%>/share/omc/runtime/c/fmi/buildproject/* <%fileNamePrefix%>.fmutmp/sources
<%\t%>cp -a <%fileNamePrefix%>_FMU.libs <%fileNamePrefix%>.fmutmp/sources/
<%\n%>
>>
Expand Down
7 changes: 6 additions & 1 deletion SimulationRuntime/c/Makefile.common
Expand Up @@ -4,6 +4,8 @@
# If you need to add files, etc, you modify Makefile.common - a common file
# for both UNIX/Linux and Windows platforms.

# Forces the generation of the dgesv sources
NEED_DGESV=1
include Makefile.objs

OMC_MINIMAL_RUNTIME=
Expand Down Expand Up @@ -248,8 +250,11 @@ clean:
(! test -f $(EXTERNALCBUILDDIR)/Makefile) || make -C $(EXTERNALCBUILDDIR) clean
(! test -f $(EXTERNALCBUILDDIR)/Makefile) || make -C $(EXTERNALCBUILDDIR) distclean

sourcedist:
sourcedist: sourcedist1 sourcedist2
sourcedist1:
$(MAKE) -f $(LIBMAKEFILE) OMC_MINIMAL_RUNTIME=1 OMC_FMI_RUNTIME=1 sourcedist_internal
sourcedist2:
$(MAKE) -C ../fmi/export/buildproject

sourcedist_internal:
mkdir -p $(builddir_inc)/c/external_solvers external_solvers
Expand Down
3 changes: 3 additions & 0 deletions SimulationRuntime/c/Makefile.objs
Expand Up @@ -123,9 +123,12 @@ ALL_OBJS = $(METAOBJSPATH) $(UTILOBJSPATH) $(MATHOBJSPATH) $(SOLVEROBJSPATH) $(I

# External solvers needed by FMI for ME
CMINPACK_OBJS = enorm_ hybrj_ dpmpar_ qrfac_ qform_ dogleg_ r1updt_ r1mpyq_
ifneq ($(NEED_DGESV),)
LAPACK_OBJS = dgesv dgetrf dlamch dtrtrs ilaenv ilazlr xerbla zlarfb zlarft zungbr zunglq dgetf2 dgetrs dlaswp ieeeck ilazlc iparmq zlacgv zlarf zung2r zungl2 zungqr
BLAS_OBJS = dgemm dger dscal dswap dtrsm idamax lsame zcopy zgemm zgemv zgerc zscal ztrmm ztrmv
LIBF2C_OBJS = d_cnjg i_len i_nint pow_di s_cmp s_copy
endif

# Only objects needed for FMI for Modelica Exchange
FMI_ME_OBJS = $(UTILOBJSPATH) $(MATHOBJSPATH) $(SIMOBJSPATHC) $(SOLVEROBJSPATH) $(INITIALIZATIONOBJSPATH) \
./meta/meta_modelica_catch$(OBJ_EXT) \
Expand Down
1 change: 1 addition & 0 deletions SimulationRuntime/c/simulation/modelinfo.c
Expand Up @@ -35,6 +35,7 @@
#include "simulation_info_json.h"
#include "simulation_runtime.h"
#include "util/omc_mmap.h"
#include "solver/model_help.h"


#include <errno.h>
Expand Down
1 change: 1 addition & 0 deletions SimulationRuntime/c/simulation/simulation_info_json.c
Expand Up @@ -35,6 +35,7 @@
#include <stdio.h>
#include "util/rtclock.h"
#include "util/omc_mmap.h"
#include "solver/model_help.h"

static inline const char* skipSpace(const char* str)
{
Expand Down
2 changes: 0 additions & 2 deletions SimulationRuntime/c/simulation/simulation_runtime.h
Expand Up @@ -60,8 +60,6 @@ extern int initializeResultData(DATA* simData, threadData_t *threadData, int cpu

#endif /* cplusplus */

extern int measure_time_flag;

extern int modelTermination; /* Becomes non-zero when simulation terminates. */
extern int terminationTerminate; /* Becomes non-zero when user terminates simulation. */
extern int terminationAssert; /* Becomes non-zero when model call assert simulation. */
Expand Down
2 changes: 2 additions & 0 deletions SimulationRuntime/c/simulation/solver/model_help.c
Expand Up @@ -1319,3 +1319,5 @@ modelica_real _event_div_real(modelica_real x1, modelica_real x2, modelica_integ
return trunc(value1/value2);
#endif
}

int measure_time_flag=0;
2 changes: 2 additions & 0 deletions SimulationRuntime/c/simulation/solver/model_help.h
Expand Up @@ -151,6 +151,8 @@ modelica_boolean LessEqZC(double a, double b, modelica_boolean);
modelica_boolean GreaterZC(double a, double b, modelica_boolean);
modelica_boolean GreaterEqZC(double a, double b, modelica_boolean);

extern int measure_time_flag;

#ifdef __cplusplus
}
#endif
Expand Down
15 changes: 15 additions & 0 deletions SimulationRuntime/fmi/export/buildproject/Makefile.in
@@ -0,0 +1,15 @@
# Manually created Makefile

top_builddir = @top_builddir@
PROJECTDIR = @OMBUILDDIR@/share/omc/runtime/c/fmi/buildproject/

default: install

all: configure

configure: configure.ac
autoconf

install: all
mkdir -p $(PROJECTDIR)
cp -a configure $(top_builddir)/config.guess $(top_builddir)/config.sub $(top_builddir)/install-sh $(PROJECTDIR)/
6 changes: 6 additions & 0 deletions SimulationRuntime/fmi/export/buildproject/README.md
@@ -0,0 +1,6 @@
FMI build project
=================

This build project is generated during the build process and put in the
shared files. The reason for this is that the Windows installer does not
include autoconf.
163 changes: 163 additions & 0 deletions SimulationRuntime/fmi/export/buildproject/configure.ac
@@ -0,0 +1,163 @@
Process this file with autoconf to produce a configure script.

AC_PREREQ([2.63])
AC_INIT([OpenModelica Exported FMU],[dev],[https://trac.openmodelica.org/OpenModelica],[openmodelica],[https://openmodelica.org])

AC_SUBST(DLLEXT)
AC_SUBST(FMIPLATFORM)
AC_SUBST(NEED_DGESV)
AC_SUBST(NEED_RUNTIME)

AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET

build_short=$build_cpu-$build_os
host_short=$host_cpu-$host_os

echo "build_short: $build_short"
echo "host_short: $host_short"

dnl Checks for programs.
AC_LANG([C])
AC_PROG_CC
AC_PROG_CPP
AC_PROG_MAKE_SET

AC_MSG_CHECKING([for cross-compilation flags])
if test "$host_short" = "$build_short"; then
# Not cross-compiling or found a good tool; don't need special flags
AC_MSG_RESULT([not cross-compiling])
elif echo "$CC" | grep -q "$host_short" || echo "$CC" | grep -q "$host"; then
AC_MSG_RESULT([not needed; $CC contains the prefix])
elif test "$host_short" = "x86_64"; then
CFLAGS_BEFORE="$CFLAGS"
CFLAGS="$CFLAGS -m64"
AC_TRY_LINK([void abc() {}], [abc();], [AC_MSG_RESULT([-m64])], [AC_MSG_ERROR([-m64 not working])])
elif echo "$host_short" | grep -q "i.86"; then
CFLAGS_BEFORE="$CFLAGS"
CFLAGS="$CFLAGS -m32"
LDFLAGS="$LDFLAGS -m32"
AC_TRY_LINK([void abc() {}], [abc();], [AC_MSG_RESULT([-m32])], [AC_MSG_ERROR([-m32 not working])])
else
AC_MSG_ERROR([unknown platform])
fi

if flase; then
CC_BEFORE="$CC"
CC="clang -target $host_short"
AC_MSG_CHECKING([looking for $CC to replace $CC_BEFORE])
AC_TRY_LINK([void abc() {}], [abc();], [AC_MSG_RESULT([yes])], [CC="$CC_BEFORE";AC_MSG_RESULT([no])])
fi

LDFLAGS_BEFORE="$LDFLAGS"
LDFLAGS="$LDFLAGS -Wl,--no-undefined"
AC_MSG_CHECKING([looking for --no-undefined])
AC_TRY_LINK([void abc() {}], [abc();], [AC_MSG_RESULT([yes]);LD_NOUNDEFINED=" -Wl,--no-undefined"], [AC_MSG_RESULT([no])])
LDFLAGS="$LDFLAGS_BEFORE"

CFLAGS_BEFORE="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
AC_MSG_CHECKING([if -Werror works])
AC_TRY_LINK([void abc() {}], [abc();], [AC_MSG_RESULT([ok])], [AC_MSG_ERROR([failed (check your CFLAGS)])])
CFLAGS="$CFLAGS_BEFORE"

dnl Disables the default CFLAGS="-g -O2"

LDFLAGS="$LDFLAGS -shared"

TRY_FLAGS="-fno-stack-protector -Wno-parentheses-equality -Wno-unused-variable -fPIC"

for flag in $TRY_FLAGS; do
OLD_CFLAGS="$CFLAGS"
CFLAGS="$RUNTIMECFLAGS $flag -Werror"
AC_TRY_LINK([], [return 0;], [CFLAGS="$OLD_CFLAGS $flag"],[CFLAGS="$OLD_CFLAGS"])
done
OLD_CFLAGS="$CFLAGS"

if test "`getconf LONG_BIT`" = "32"; then
dnl Simulations spin forever unless -msse2 -mfpmath=sse is set

CFLAGS_BEFORE=$CFLAGS
CFLAGS="-mfpmath=sse -Werror"
AC_MSG_CHECKING([for floating point bugs])
AC_TRY_LINK([int abc() {}], [abc();], [AC_MSG_RESULT([force SSE2]); FPMATHFORTRAN="-msse -mfpmath=sse"], [AC_MSG_RESULT([no]); FPMATHFORTRAN=-ffloat-store])
CFLAGS=$CFLAGS_BEFORE

fi # End x86-specific CFLAGS

dnl Checks for libraries.

dnl Checks for header files.
AC_HEADER_STDC

dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T

dnl Checks for library functions.
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strdup strerror)

# Cannot use AX_LAPACK since it assumes a Fortran compiler is used
AC_ARG_WITH(lapack, [ --with-lapack=[-llapack -lblas] (use -llapack -lblas to use system-provided version.)],[LD_LAPACK="$withval"],[
LD_LAPACK="-Wl,-Bstatic -llapack -lblas -Wl,-Bdynamic"
])

AC_MSG_CHECKING([LAPACK/BLAS flags])

OLDLIBS="$LIBS"
LIBS="$LIBS $LD_LAPACK"
AC_LINK_IFELSE([AC_LANG_CALL([], [dgesv_])],[
AC_LINK_IFELSE([AC_LANG_CALL([], [dswap_])],[AC_MSG_RESULT([$LD_LAPACK])],[LIBS="$OLDLIBS"; NEED_DGESV=1; AC_MSG_RESULT([dswap (BLAS) linking failed using $LD_LAPACK])])
],[LIBS="$OLDLIBS"; NEED_DGESV=1; AC_MSG_RESULT([dgesv (LAPACK) linking failed using $LD_LAPACK])])

AC_MSG_CHECKING([for static pthreads])
OLDLIBS=$LIBS
LIBS="$OLDLIBS -Wl,-Bstatic -lpthread -Wl,-Bdynamic"
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_mutex_lock])],[AC_MSG_RESULT([OK (static)])],[
AC_MSG_RESULT([no])
LIBS="$OLDLIBS"
AC_CHECK_LIB(pthread,[pthread_mutex_lock],[],[AC_MSG_ERROR([pthreads not found])])
])

AC_CHECK_LIB([m],[cos],[],[AC_MSG_ERROR([math library not found])])

AC_ARG_WITH(dynamic-om-runtime, [ --with-dynamic-om-runtime (uses the OMC runtime as a shared object instead of compiling it statically into the the FMU.)],[OPENMODELICADYNAMIC=yes],[OPENMODELICADYNAMIC=no])

if test "$OPENMODELICADYNAMIC" = "no"; then
CPPFLAGS="$CPPFLAGS -DOMC_MINIMAL_RUNTIME=1 -DCMINPACK_NO_DLL=1"
NEED_RUNTIME=1
fi

if test "$host_os" = darwin; then
DLLEXT=".dylib"
if echo "$host_cpu" | grep -q i@<:@3456@:>@86; then
FMIPLATFORM=darwin32
elif echo "$host_cpu" | grep -q x86_64; then
FMIPLATFORM=darwin64
fi
elif echo "$host_os" | grep -q mingw; then
DLLEXT=".dll"
if echo "$host_cpu" | grep -q i@<:@3456@:>@86; then
FMIPLATFORM=win32
elif echo "$host_cpu" | grep -q x86_64; then
FMIPLATFORM=win64
fi
elif echo "$host_os" | grep -q linux; then
DLLEXT=".so"
if echo "$host_cpu" | grep -q i@<:@3456@:>@86; then
FMIPLATFORM=linux32
elif echo "$host_cpu" | grep -q x86_64; then
FMIPLATFORM=linux64
fi
else
DLLEXT=".so"
fi

# Non-standard platforms also need some love
if test -z "$FMIPLATFORM"; then
FMIPLATFORM=$host_short
fi

AC_OUTPUT(Makefile)
2 changes: 1 addition & 1 deletion common
Submodule common updated 1 files
+21 −2 m4/qmake.m4

0 comments on commit e89eaf5

Please sign in to comment.