旧的Fortran程序:ld返回了1个退出状态。

3
我有一个老的FORTRAN 77程序,我在使用以下命令进行编译/构建时遇到了问题: gfortran -Wall -o "文件名" 文件名.f 它一直给我链接器错误提示:
$ gfortran -Wall  ljewald.f 

/usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status

最终,我尝试了:gfortran -Wall -c -o "文件名" 文件名.f 这个命令生成了可执行二进制文件。很好,但是 gfortran 的 man 手册让我感到有些困惑。下面是 -c 选项的相关内容,这个选项使得编译工作变得更加顺利:
   -C  Do not discard comments. All comments are passed through to the output file, except for comments in processed directives, which are deleted
       along with the directive.

       You should be prepared for side effects when using -C; it causes the preprocessor to treat comments as tokens in their own right. For example,
       comments appearing at the start of what would be a directive line have the effect of turning that line into an ordinary source line, since the
       first token on the line is no longer a '#'.

       Warning: this currently handles C-Style comments only. The preprocessor does not yet recognize Fortran-style comments.

因此,在构建完成后,使用以下命令: gfortran -Wall -c -o "ljewald" ljewald.f

我得到了一个输出文件,但它不是可执行文件...?

$ls -l
...
-rw-rw-r--  1 j0h j0h    647 Aug  9 16:36 ljewald 
...

即使我使用chmod +x ljewald更改模式,也无法执行此文件。

我应该怎么做才能避免-c选项,因为使用它有一些怪异之处?如何构建此程序的可执行文件?有人可以解释并告诉我如何解决吗?

/usr/lib/gcc/i686-linux-gnu/4.7/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
collect2: error: ld returned 1 exit status

链接到源代码: http://nanocluster.umeche.maine.edu/ljewald.f

你是在使用 -c 还是 -C?它们都出现在你的问题中... - Floris
我正在使用小写的c。哎呀,手册是大写的。我甚至看不到一个-c(小写选项)。 - j0h
1
使用 -c 选项可以得到一个输出文件,而使用 -C 选项会仍然得到相同的链接器错误。 - j0h
确定这是编译器还是源文件的问题:您能否编译其他任何东西(例如简单的“Hello World”程序)? - Floris
我在想,作为一个“老”文件,是否换行符没有被编译器正确识别?或者文件末尾是否缺少 EOL 等等?我无法从手机上查看文件的详细信息,但我明天回家后可以看一下。 - Floris
显示剩余3条评论
1个回答

2
编辑:问题显然不是源程序不足造成的(抱歉,我还没有清醒过来:-))。
实际上,换行符引起了问题:当在Windows上正确转换为CRLF时,gcc-4.8.1可以成功编译(在注释掉ACCEPT后)。
但是:
  • 有很多警告(未使用的变量或格式)
  • ACCEPT应该等同于READ,然后缺少标签777(对于READ格式)
  • 有一些带有制表符的行,这应该真的被避免,特别是当几乎所有代码都缩进空格时。

如果您可以访问Windows计算机,则可以使用Notepad++来转换行尾并替换制表符。

如果您有许多需要修复的文件,可以尝试使用Python脚本。您可以根据需要修改以下示例中的cleanfile函数,该函数根据给定的规则清理文件(这里将换行符转换为CRLF并删除无用的空格)。此示例在Python 3中编写,但如有需要,很容易转换为Python 2。
# encoding: ISO-8859-15

import sys, os, hashlib

def filehash(name):
   f = open(name, "rb")
   h = hashlib.sha512()
   n = 4 * 1024 * 1024
   while True:
      r = f.read(n)
      h.update(r)
      if len(r) < n:
         break
   f.close()
   return h.hexdigest()

def cleanfile(name):
   v = os.stat(name)
   a = filehash(name)
   atime = v[7]
   mtime = v[8]
   f = open(name, "rt", encoding="ISO-8859-1")
   u = f.readlines()
   f.close()

   n = len(u)
   for i in range(n):
      u[i] = u[i].rstrip()

   while n > 0 and u[n - 1] == "":
      n -= 1

   if n == 0:
      print("EMPTY FILE {}".format(name))
      os.remove(name)
      return

   #f = open(name, "wt", newline="\n")
   f = open(name, "wt", encoding="ISO-8859-1")
   for i in range(n):
      s = u[i]
      f.write("{}\n".format(s))
   f.close()

   os.utime(name, (atime, mtime))
   b = filehash(name)
   if a != b:
      print("MODIF {}".format(name))

def manfile(name):
   global exts
   n = name.rfind(".")
   if n < 0:
      print("PASS {}".format(name))
   e = name[n + 1:].lower()

   if e in ["f"]:
      cleanfile(name)
   else:
      print("SKIP {}  -  {}".format(e, name))


########### recursive directory traversal, don't whange after this line ###########

def mandir(path):
   try:
      li = os.listdir(path)
   except:
      print("ERRD {}".format(path))
      return
   li.sort()
   lilnk = [ ]
   lifil = [ ]
   lidir = [ ]
   for name in li:
      c = os.path.join(path, name)
      if os.path.islink(c):
         lilnk.append(c)
      elif os.path.isfile(c):
         lifil.append(c)
      elif os.path.isdir(c):
         lidir.append(c)
      else:
         print("UNKN {}".format(c))
   for c in lilnk:
      os.remove(c)
      pass
   for c in lifil:
      manfile(c)
   for c in lidir:
      mandir(c)
   li = os.listdir(path)
   if len(li) == 0:
      try:
         os.rmdir(path)
      except OSError:
         pass

mandir(sys.argv[1])

是的。除了我使用的是Windows,而且我做的不仅仅是转换行尾(删除尾随空格,检查缩进或存在坏字符,仅对选定的文件进行操作等)。上面的脚本只是递归目录搜索的基础,cleanfilemanfile函数可以适应许多事情,并且它对我很有帮助。我想也许它也能帮助其他人... - user1220978
很抱歉耽搁了这么久,但是标记为已解决真的在那时候帮了我大忙! - j0h

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接