ปัญหา makefile ของ gfortran

ฉันมีโปรแกรมเขียนบน Fortran ซึ่งใช้ไลบรารี่ สำหรับการคอมไพล์ ฉันใช้เชลล์สคริปต์อย่างง่าย และทุกอย่างเรียบร้อยดี:

gfortran -c mod_input.f90 mod_cpp.f90 mod_data.f90 main.f90 b_coils.f

gfortran -o หลัก mod_input.o mod_cpp.o mod_data.o main.o b_coils.o libspline.a -lstdc++

(libspline.a - การเขียนไลบรารีบน c++)

ตอนนี้ฉันต้องการใช้ makefile แทนเชลล์สคริปต์ แต่ไม่รู้วิธีเขียนอย่างถูกต้อง

เมคไฟล์:

target = main
srcdir = src/
objdir = obj/
targetdir = run/

FORT = gfortran
mflag = module
FORTFLAGS =
LDFLAGS = -lstdc++  

MKLPATH =/home/gatto/Desktop/ray_u3/src
LIBDIR  =-L$(MKLPATH)
LIBS = -lspline                                                             
MODDIR = obj/                                                           

# Ray sources
sources = mod_input.f90 mod_cpp.f90 mod_data.f90  main.f90 b_coils.f


# objects
objects  = $(patsubst %.for,%.o,$(filter %for,$(sources)) )
objects += $(patsubst %.f90,%.o,$(filter %f90,$(sources)) )

# main target
build:$(targetdir)$(target)

# build rules
$(targetdir)$(target):$(addprefix $(objdir),$(objects))
    @echo === build $@ ===
    $(FORT) $(FORTFLAGS) $(LDFLAGS) $(LIBDIR) -o $@ $(LIBS) $^

#compilation target
compile :$(addprefix $(objdir),$(objects))

# compilation rules
$(objdir)%.o : $(srcdir)%.f90
    @echo === compile $< ===
    $(FORT) -c $(objdir) $(FORTFLAGS) -o $@ $<

$(objdir)%.o : $(srcdir)%.f
    @echo === compile $< ===
    $(FORT) -c $(objdir) $(FORTFLAGS) -o $@ $<


# cleaning rules
cleanobj:
    -rm $(objdir)*.o $(objdir)*.mod
cleantarget:
    -rm $(targetdir)$(target)

cleanall:cleanobj cleantarget

.PHONY: compile build cleanall cleanobj cleantarget

ผลลัพธ์:

gfortran  -lstdc++   -L/home/gatto/Desktop/ray_u3/src -o run/main -lspline obj/mod_input.o obj/mod_cpp.o obj/mod_data.o obj/main.o
obj/mod_data.o: In function `__global_data_MOD_modbfield':
mod_data.f90:(.text+0x3e2): undefined reference to `gbcoil_'
obj/mod_data.o: In function `__global_data_MOD_moddensity':
mod_data.f90:(.text+0x5d4): undefined reference to `GetSplineValue'
mod_data.f90:(.text+0x64f): undefined reference to `GetSplineValue'
mod_data.f90:(.text+0x6ca): undefined reference to `GetSplineValue'
mod_data.f90:(.text+0x745): undefined reference to `GetSplineValue'
obj/mod_data.o: In function `__global_data_MOD_inpfile':
mod_data.f90:(.text+0xa66): undefined reference to `Approx_input'
mod_data.f90:(.text+0xa75): undefined reference to `SetSpline'
collect2: error: ld returned 1 exit status
make: *** [run/main] Error 1

person Gatto Nou    schedule 10.12.2015    source แหล่งที่มา
comment
เริ่มต้นด้วยการเยื้อง คำสั่งสำหรับกฎจะต้องเยื้องด้วยแท็บเดียว เมื่อคุณแก้ไขแล้ว ให้กลับมาและอัปเดตคำถามเพื่อรวมปัญหาจริงที่คุณมีกับ makefile เช่นบอกเราว่าเกิดอะไรขึ้นคุณลองใช้มัน รวมเอาต์พุตทั้งหมด ครบถ้วนและไม่มีการแก้ไข   -  person Some programmer dude    schedule 10.12.2015
comment
คุณมีข้อมูลโค้ด makefile ที่นี่ซึ่งใช้ตัวแปรจำนวนมากที่ไม่ได้กำหนดไว้ในที่ใดก็ตามที่เราเห็น คุณต้องแสดงตัวอย่างที่สมบูรณ์ให้เราดู และตามที่ Joachim ระบุไว้ คำสั่งที่คุณกำลังรันและผลลัพธ์/ผลลัพธ์ที่คุณได้รับ   -  person Etan Reisner    schedule 10.12.2015
comment
ฉันแก้ไขโพสต์ของฉันแล้ว   -  person Gatto Nou    schedule 10.12.2015
comment
คุณได้ลองย้าย $^ ของคุณก่อน $(LIBS) แล้วหรือยัง? ลำดับมีความสำคัญเมื่อทำการเชื่อมโยง ดังนั้นจึงอาจเป็นเรื่องง่ายๆ เช่นนั้น   -  person jefflarkin    schedule 10.12.2015
comment
ทำไมคุณไม่ทำตามบทช่วยสอน makefile หากคุณยังใหม่กับ makefiles? ตัวอย่างเช่น cs.colby.edu/maxwell/courses/tutorials/maketutor หรือ cs.usask.ca/staff/oster/makefiles.html หรือ google เพื่อการกวดวิชาที่สะดวกยิ่งขึ้น   -  person innoSPG    schedule 10.12.2015


คำตอบ (1)


ฉันขอแนะนำให้คุณใช้ automake (และ autoconf) มันมี metatags จำนวนมาก แต่สำหรับโปรแกรมธรรมดา มันเร็วกว่าในการเขียน และในกรณีส่วนใหญ่ คุณอาจพบว่าตัวเองดำเนินการเปลี่ยนแปลงเพียงเล็กน้อย (เช่น filename)

นี่คืออินพุต autoconf และ automake ของฉันสำหรับโปรเจ็กต์ที่คล้ายกัน ซึ่งเพิ่งใช้ lapack แทนที่จะเป็น mkl

กำหนดค่า.ac

#AC_PREREQ(2.69)
AC_INIT([src], [0.1],
    [],
    [mftc],
    [])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

AM_INIT_AUTOMAKE([1.9.6 dist-bzip2 subdir-objects foreign])

AC_SEARCH_LIBS([dsyev_], [lapack], ,AC_MSG_ERROR([No LAPACK library]))
AC_OPENMP
FCFLAGS="$OPENMP_FFLAGS "
AC_PROG_FC([gfortran, ifort])
AC_CHECK_PROG([DEPF90_CHECK],[makedepf90],[yes],[no])
AM_CONDITIONAL([FOUND_MAKEDEPF90], [test "x$DEPF90_CHECK" = xyes])
AC_CONFIG_FILES([
         Makefile
         ])
AC_OUTPUT

Makefile.am

bin_PROGRAMS =  mftc
mftc_SOURCES = src/mftc.f90  src/parse.f90 src/sort.f90
depend depend.mk:
    makedepf90 $(mftc_SOURCES) >depend.mk
@am__include@ @[email protected]@am__quote@
mftc_LDADD = 
EXTRA_DIST=depend.mk autogen.sh Makefile.am
CLEANFILES =*.mod  *.log

depend depend.mk ขึ้นอยู่กับโปรแกรม makedepf90 ซึ่งมีอยู่ในแพลตฟอร์ม Linux ส่วนใหญ่ โปรแกรมนี้ดูแลการขึ้นต่อกัน (นั่นคือโมดูลจะถูกคอมไพล์ก่อนโปรแกรม)

การใช้งาน หากคุณพอใจกับ LAPACK ฉันไม่เห็นสิ่งใดให้คุณเปลี่ยนแปลงใน configuration.ac เปลี่ยนบรรทัด _SOURCES สำหรับชื่อไฟล์ที่ถูกต้อง ตอนนี้มันเป็น 3 คำสั่งในเทอร์มินัล:

 $autoconf 
 $./configure 
 $make

แน่นอนว่าคุณต้องติดตั้ง automake และ autoconf ด้วย

หวังว่านี่จะช่วยได้

person BaRud    schedule 11.12.2015